import random
import psyco
import cProfile
import struct 
import ctypes #create_string_buffer

#psyco.profile()
psyco.full()

class database:
    @staticmethod
    def write_5hands_rank_and_highcards(filehandle=None):
        number_of_cards = 52
        count = 0
        output_string = ""
        d = deck()
        buffer = ctypes.create_string_buffer(11)

        for i in range(number_of_cards-4):
            for j in range(i+1,number_of_cards-3):
                for k in range(j+1, number_of_cards-2):
                    for l in range(k+1, number_of_cards-1):
                        for m in range(l+1, number_of_cards):
                            #count += 1
                            h = hand(d.cards[i], d.cards[j], d.cards[k], d.cards[l], d.cards[m])
			
                            #write cards and rank
                            struct.pack_into('bbbbbb', buffer, 0,\
                                    card.card_to_rawnumber(d.cards[i]),\
                                    card.card_to_rawnumber(d.cards[j]),\
                                    card.card_to_rawnumber(d.cards[k]),\
                                    card.card_to_rawnumber(d.cards[l]),\
                                    card.card_to_rawnumber(d.cards[m]), h.rank)

                            #write high cards
                            if h.rank==0 or h.rank==5:
                                #these ranks have 5 high cards
                                struct.pack_into('bbbbb', buffer, 6, \
                                        card.card_to_rawnumber(h.highcards[0]),\
                                        card.card_to_rawnumber(h.highcards[1]),\
                                        card.card_to_rawnumber(h.highcards[2]),\
                                        card.card_to_rawnumber(h.highcards[3]),\
                                        card.card_to_rawnumber(h.highcards[4]))
                            elif h.rank==1:
                                #these ranks has 1pair and 3 high cards
                                struct.pack_into('bbbb', buffer, 6, \
                                        card.card_to_rawnumber(h.highcards[0]),\
                                        card.card_to_rawnumber(h.highcards[1]),\
                                        card.card_to_rawnumber(h.highcards[2]),\
                                        card.card_to_rawnumber(h.highcards[3]))
                            elif h.rank==2:
                                #these ranks has 2pairs and high card
                                struct.pack_into('bbb', buffer, 6, \
                                        card.card_to_rawnumber(h.highcards[0]),\
                                        card.card_to_rawnumber(h.highcards[1]),\
                                        card.card_to_rawnumber(h.highcards[2]))
                            elif h.rank==8 or h.rank==7 or h.rank==6 or h.rank==4 or h.rank==3:
                                #these ranks only have one high card
                                struct.pack_into('b', buffer, 6, \
                                        card.card_to_rawnumber(h.highcards[0]))
                            filehandle.write(buffer)

        print count

    @staticmethod
    def write_7hands_rank_and_highcards(filehandle=None):
        number_of_cards = 52
        count = 0
        output_string = ""
        d = deck()
        buffer = ctypes.create_string_buffer(11)

        for i in range(number_of_cards-4):
            for j in range(i+1,number_of_cards-3):
                for k in range(j+1, number_of_cards-2):
                    for l in range(k+1, number_of_cards-1):
                        for m in range(l+1, number_of_cards):
                            for n in range(k+1, number_of_cards-1):
                                for o in range(l+1, number_of_cards):
                                    #count += 1
                                    h = hand(d.cards[i], d.cards[j], d.cards[k], d.cards[l], d.cards[m])
                    
                                    #write cards and rank
                                    struct.pack_into('bbbbbb', buffer, 0,\
                                            card.card_to_rawnumber(d.cards[i]),\
                                            card.card_to_rawnumber(d.cards[j]),\
                                            card.card_to_rawnumber(d.cards[k]),\
                                            card.card_to_rawnumber(d.cards[l]),\
                                            card.card_to_rawnumber(d.cards[m]), h.rank)

                                    #write high cards
                                    if h.rank==0 or h.rank==5:
                                        #these ranks have 5 high cards
                                        struct.pack_into('bbbbb', buffer, 6, \
                                                card.card_to_rawnumber(h.highcards[0]),\
                                                card.card_to_rawnumber(h.highcards[1]),\
                                                card.card_to_rawnumber(h.highcards[2]),\
                                                card.card_to_rawnumber(h.highcards[3]),\
                                                card.card_to_rawnumber(h.highcards[4]))
                                    elif h.rank==1:
                                        #these ranks has 1pair and 3 high cards
                                        struct.pack_into('bbbb', buffer, 6, \
                                                card.card_to_rawnumber(h.highcards[0]),\
                                                card.card_to_rawnumber(h.highcards[1]),\
                                                card.card_to_rawnumber(h.highcards[2]),\
                                                card.card_to_rawnumber(h.highcards[3]))
                                    elif h.rank==2:
                                        #these ranks has 2pairs and high card
                                        struct.pack_into('bbb', buffer, 6, \
                                                card.card_to_rawnumber(h.highcards[0]),\
                                                card.card_to_rawnumber(h.highcards[1]),\
                                                card.card_to_rawnumber(h.highcards[2]))
                                    elif h.rank==8 or h.rank==7 or h.rank==6 or h.rank==4 or h.rank==3:
                                        #these ranks only have one high card
                                        struct.pack_into('b', buffer, 6, \
                                                card.card_to_rawnumber(h.highcards[0]))
                                    filehandle.write(buffer)

        print count

    @staticmethod
    def read_5hands_rank_and_highcards(filehandle=None):
        number_of_cards = 52
        count = 0
        output_string = ""
        d = deck()

        print "hehe"
        for i in range(number_of_cards-4):
            for j in range(i+1,number_of_cards-3):
                for k in range(j+1, number_of_cards-2):
                    for l in range(k+1, number_of_cards-1):
                        for m in range(l+1, number_of_cards):
                            count += 1
                            h = hand(d.cards[i], d.cards[j], d.cards[k], d.cards[l], d.cards[m])
                            #h.rank
                            #h.highcards
			

                            filehandle.write( struct.pack('b', card.card_to_rawnumber(d.cards[i])) )
                            filehandle.write( struct.pack('b', card.card_to_rawnumber(d.cards[j])) )
                            filehandle.write( struct.pack('b', card.card_to_rawnumber(d.cards[k])) )
                            filehandle.write( struct.pack('b', card.card_to_rawnumber(d.cards[l])) )
                            filehandle.write( struct.pack('b', card.card_to_rawnumber(d.cards[m])) )
                            filehandle.write( struct.pack('b', h.rank) )
                            for i in range(5): #write the 1 to 5 high cards
                                if i < len(h.highcards): 
                                    #print h.highcards[i],
                                    filehandle.write( struct.pack('b', card.card_to_rawnumber(h.highcards[i])) )
                                else:
                                    #print "blank",
                                    filehandle.write( struct.pack('b', 0) )

        print count
class game:
    def __init__(self):
        pass

    """
    def __init__(self, p1, p2, f1, f2, f3, t, r, d1, d2, bets):
        winnings = 0
        self.player_hand = hand(f1, f2, f3, t, r, p1, p2)
        self.dealer_hand = hand(f1, f2, f3, t, r, d1, d2)
        if self.player_hand > self.dealer_hand:
            winnings = 0
        elif self.player_hand == self.dealer_hand:
            winnings = 0
        else:
            winnings = 0
    """

    def permutation_of_7_cards(self):
        number_of_cards = 52
        count = 0
        output_string = ""
        d = deck()

        for i in range(number_of_cards-4):
            for j in range(i+1,number_of_cards-3):
                for k in range(j+1, number_of_cards-2):
                    for l in range(k+1, number_of_cards-1):
                        for m in range(l+1, number_of_cards):
                            for n in range(m+1, number_of_cards):
                                for o in range(n+1, number_of_cards):
                                    count += 1
                                    """
                                    print "%9d %s%s %s%s%s %s%s" %( \
                                            count,
                                            d.cards[i].__str__(),\
                                            d.cards[j].__str__(),\
                                            d.cards[k].__str__(),\
                                            d.cards[l].__str__(),\
                                            d.cards[m].__str__(), \
                                            d.cards[n].__str__(),\
                                            d.cards[o].__str__(),)
                                    #print "%9d" %( count,)
                                    """ 
        print count
        print output_string

    def permutation_of_5_cards(self):
        number_of_cards = 52
        count = 0
        output_string = ""
        d = deck()

        for i in range(number_of_cards-4):
            for j in range(i+1,number_of_cards-3):
                for k in range(j+1, number_of_cards-2):
                    for l in range(k+1, number_of_cards-1):
                        for m in range(l+1, number_of_cards):
                            count += 1
                            """
                            h = hand(d.cards[i], d.cards[j], d.cards[k], d.cards[l], d.cards[m])
                            print "%10d %s %s %s %s %s %d" %( \
                                    count,
                                    d.cards[i],\
                                    d.cards[j],\
                                    d.cards[k],\
                                    d.cards[l],\
                                    d.cards[m],
                                    h.rank())
                            """
                            h = hand(d.cards[i], d.cards[j], d.cards[k], d.cards[l], d.cards[m])
                            print h
        print count
        
class hand:
    def __init__(self, a=None,b=None,c=None,d=None,e=None):
        """generates a deck of 5 cards. If there are no inputs, then random cards are generated
           Note: random cards function disabled to improve performance """
        """
        if (a==b==c==d==e==None):
            #generates a deck of 5 random cards
            print #in class hand and 5 cards are blank
            self.cards = [card(), card(), card(), card(), card()]
        else:
            self.cards = [a,b,c,d,e]
        """
        self.cards = [a,b,c,d,e]
        self.cards.sort()
        self.rank = self.calculate_rank()
        self.highcards = self.calculate_highcards(self.rank)

    def __cmp__(self, otherhand):
        print "selfrank:%d otherrank:%d" % (self.rank, otherhand.rank)
        if self.rank > otherhand.rank:
            print "1"
            return 1
        elif self.rank < otherhand.rank:
            print "2"
            return -1
        else:
            #the ranks are tied
            #now we have to check for highest card
            #note that 4ofakind, cant be tied
            print "3"
            
            self_cards = self.cards[:] #make copies of the cards for poping elements off
            other_cards = otherhand.cards[:] 

            if self.rank == 0:
                #cmp high cards
                while (len(self_cards) > 0):
                    if self_cards[0].value > other_cards[0].value:
                        return 1
                    elif self_cards[0].value < other_cards[0].value:
                        return -1
                    else:
                        self_cards.pop(0)
                        other_cards.pop(0)
                return 0
        return 7777

    def calculate_rank(self):
        """based on the 5 cards, determine the rank of the hand
           returns 8, for straight flush #royal flush is not a category
                   7, for 4 of a kind
                   6, for full house
                   5, for flush
                   4, for straight
                   3, for 3 of a kind
                   2, for 2 pairs
                   1, for 1 pair
                   0, for high card
           and so return list of high cards

           Given the rank, calculate and return list of high cards for the hand
           if rank=8, for straight flush, return 1 high card
           if rank=7, for 4 of a kind,    return high card from 4ofakind
           if rank=6, for full house,     return ???  TODO ???????????????????????????????????????????????????????
           if rank=5, for flush,          return 5 high cards (A first, K next... 2 last)
           if rank=4, for straight,       return high card
           if rank=3, for 3 of a kind,    return high card from 4ofakind
           if rank=2, for 2 pairs,        return high pair, lower pair, high card
           if rank=1, for 1 pair,         return high pair, high card, high card, high card (for high cards, A first, K next... 2 last)
           if rank=0, for high card,      return 5 high cards (A first, K next... 2 last)
           if rank=others, raise Exception

           High cards is useful when your RANK tie with dealer and want to check who is winner
           eg, if your hand=Xc,6c,4c,3c,2c and rank=5 (flush)
               calculate_highcards will return Xc,6c,4c,3c,2c
           and if dealer's hand=Xc,5c,4c,3c,2c and rank=5 (flush)
               calculate_highcards will return Xc,5c,4c,3c,2c
           If you compare two returned highcards list, you will win
           because you have 6c which is higher than dealer's 5c
           """
        rank = None
        if self.has_same_suit():
            if self.is_straight():
                #print "8:is straight flush"
                rank = 8
            else:
                #print "5: is flush"
                rank = 5
        elif self.is_straight():
            #print "4: is straight"
            rank = 4
        elif self.has_at_least_one_pair():
            if self.is_4_of_a_kind():
                #print "7: is 4 of a kind"
                rank = 7
            elif self.is_full_house ():
                #print "6: is full house kind"
                rank = 6
            elif self.is_3_of_a_kind():
                #print "3: is 3 of a kind"
                rank = 3
            elif self.is_2_pairs():
                #print "2: is 2 pairs"
                rank = 2
            else:
                #print "1: is one pair"
                rank = 1
        else:
            #print "0: is high card"
            rank = 0

        assert( 0 <= rank <= 8)
        return rank

    def calculate_highcards(self, rank):
        """this chunk returns a list of high cards given the rank of the curr hand"""
        assert( 0 <= rank <= 8)
        highcards = []

        if rank == 8:
            highcards.append(self.cards[0])
        elif rank == 7:
            if self.cards[0].value == self.cards[1].value:
                highcards.append(self.cards[0])#if 4ofakind is in format KKKK2, add K
            else:#if 4ofakind is in format KQQQQ, add Q
                highcards.append(self.cards[1])
        elif rank == 6:
            #TODO: implement the correct high cards to return
            if self.cards[0].value == self.cards[1].value:
                highcards.append(self.cards[0]) #if3ofakind is in format KKKQJ, add K
            elif self.cards[-2].value == self.cards[-1].value:
                highcards.append(self.cards[-1]) #if3ofakind is in format AKJJJ, add J
            else:
                highcards.append(self.cards[1]) #else 3ofakind is in format AKKKJ, add K
        elif rank == 5:
            highcards = self.cards[:]#return all
        elif rank == 4:
            highcards.append(self.cards[0])
        elif rank == 3:
            if self.cards[0].value == self.cards[1].value:
                highcards.append(self.cards[0]) #if3ofakind is in format KKKQJ, add K
            elif self.cards[-2].value == self.cards[-1].value:
                highcards.append(self.cards[-1]) #if3ofakind is in format AKJJJ, add J
            else:
                highcards.append(self.cards[1]) #else 3ofakind is in format AKKKJ, add K
        elif rank == 2:
            if   self.cards[0].value == self.cards[1].value and\
                 self.cards[2].value == self.cards[3].value:#if 2pairs in format KKQQJ, add K,Q,J
                highcards.append(self.cards[0]) 
                highcards.append(self.cards[2]) 
                highcards.append(self.cards[-1]) 
            elif self.cards[1].value == self.cards[2].value and\
                 self.cards[3].value == self.cards[4].value:#if 2pairs in format KQQJJ, add Q,J,K
                highcards.append(self.cards[1]) 
                highcards.append(self.cards[3]) 
                highcards.append(self.cards[0]) 
            else: #else 2pairs in format KKQJJ, add K,Q,J
                highcards.append(self.cards[0]) 
                highcards.append(self.cards[3]) 
                highcards.append(self.cards[2]) 
        elif rank == 1:
            if self.cards[0].value == self.cards[1].value:
                highcards.append(self.cards[0])
                highcards.append(self.cards[2])
                highcards.append(self.cards[3])
                highcards.append(self.cards[4])
            elif self.cards[1].value == self.cards[2].value:
                highcards.append(self.cards[1])
                highcards.append(self.cards[0])
                highcards.append(self.cards[3])
                highcards.append(self.cards[4])
            elif self.cards[2].value == self.cards[3].value:
                highcards.append(self.cards[2])
                highcards.append(self.cards[0])
                highcards.append(self.cards[1])
                highcards.append(self.cards[4])
            else:
                highcards.append(self.cards[3])
                highcards.append(self.cards[0])
                highcards.append(self.cards[1])
                highcards.append(self.cards[2])
        elif rank == 0:
            highcards = self.cards[:]#return all

        assert( not (highcards == []) )
        return highcards


    def __str__(self):
        returnstring = "hand: %d |%s %s %s %s %s | " % ( self.rank,\
                self.cards[0], self.cards[1], self.cards[2], self.cards[3], self.cards[4])
        for highcard in self.highcards:
            returnstring += highcard.__str__() + " "

        return returnstring


    def has_at_least_one_pair(self):
        #return True if there is at least one pair, else return False
        a = self.cards[0]
        b = self.cards[1]
        c = self.cards[2]
        d = self.cards[3]
        e = self.cards[4]
        return  a.value == b.value or \
                a.value == c.value or \
                a.value == d.value or \
                a.value == e.value or \
                b.value == c.value or \
                b.value == d.value or \
                b.value == e.value or \
                c.value == d.value or \
                c.value == e.value or \
                d.value == e.value

    def is_straight(self):
        a = self.cards[0]
        b = self.cards[1]
        c = self.cards[2]
        d = self.cards[3]
        e = self.cards[4]
        if a.value == 14 and \
            b.value == 5  and\
            c.value == 4  and\
            d.value == 3 and \
            e.value == 2 : 
            return True
        if a.value == b.value+1 and \
            b.value == c.value+1 and\
            c.value == d.value+1 and\
            d.value == e.value+1: 
            return True
        return False

    def has_same_suit(self):
        a = self.cards[0]
        b = self.cards[1]
        c = self.cards[2]
        d = self.cards[3]
        e = self.cards[4]
        return a.suit == b.suit and \
                b.suit == c.suit and \
                c.suit == d.suit and \
                d.suit == e.suit and \
                e.suit == a.suit 

    def is_royal_flush(self):
        a = self.cards[0]
        b = self.cards[1]
        c = self.cards[2]
        d = self.cards[3]
        e = self.cards[4]
        if self.is_straight() and self.has_same_suit():
            if a.value == 14 and \
                b.value == 13 and \
                c.value == 12 and \
                d.value == 11 and \
                e.value == 10:
                return True
        return False

    def is_full_house(self):
        if card.has_same_value(self.cards[:3]) and \
            card.has_same_value(self.cards[3:]):
            #if fullhouse is in format of KKK33, return True
            return True
        elif card.has_same_value(self.cards[:2]) and \
            card.has_same_value(self.cards[2:]):
            #if fullhouse is in format of KK333, return True
            return True
        return False

    def is_3_of_a_kind(self):
        if card.has_same_value(self.cards[:3]) and \
            self.cards[0] != self.cards[3] and\
            self.cards[3] != self.cards[4]:
            #if 3 of kind are in format of KKK32, return True
            return True
        elif card.has_same_value(self.cards[1:5]) and \
            self.cards[0] != self.cards[1] and\
            self.cards[1] != self.cards[4]:
            #if 3 of kind are in format of K3332, return True
            return True
        elif card.has_same_value(self.cards[2:]) and \
            self.cards[0] != self.cards[1] and\
            self.cards[1] != self.cards[2]:
            #if 3 of kind are in format of K3222, return True
            return True
        return False

    def is_2_pairs(self):
        a = self.cards[0]
        b = self.cards[1]
        c = self.cards[2]
        d = self.cards[3]
        e = self.cards[4]
        if card.has_same_value(self.cards[0:2]) and \
            card.has_same_value(self.cards[2:4]) and \
            self.cards[0] != self.cards[2] and\
            self.cards[2] != self.cards[4] and\
            self.cards[4] != self.cards[0]:
            #if 2pair is in format of KKJJ2, return True
            return True
        elif card.has_same_value(self.cards[0:2]) and \
            card.has_same_value(self.cards[3:5]) and \
            self.cards[0] != self.cards[3] and\
            self.cards[3] != self.cards[4] and\
            self.cards[4] != self.cards[0]:
            #if 2pair is in format of KKJ22, return True
            return True
        elif card.has_same_value(self.cards[:2]) and \
            card.has_same_value(self.cards[2:4]) and \
            self.cards[0] != self.cards[2] and\
            self.cards[2] != self.cards[4]:
            #if 2pair is in format of KJJ22, return True
            return True
        return False

    def is_4_of_a_kind(self):
        a = self.cards[0]
        b = self.cards[1]
        c = self.cards[2]
        d = self.cards[3]
        e = self.cards[4]
        if card.has_same_value(self.cards[1:]):
            return True
        elif card.has_same_value(self.cards[:-1]):
            return True
        return False

class deck:
    def __init__(self):
        self.cards = []
        values = range(2, 15)
        suits = ['c', 'h', 's', 'd']

        for  suit in suits:
            for value in values:
                self.cards.append( card(value, suit) )
        assert( len(self.cards)== 52 )

    def __str__(self):
        output_string = ""
        for i, card in enumerate(self.cards):
            if i!=0 and i%13==0:
                output_string += "\n"
            output_string += card.__str__() + " "
        return output_string

    def shuffle(self):
        random.shuffle(self.cards)

    def deal(self):
        return self.cards.pop(0)

    def generate_all_combinations3(self):
        n = 6
        count = 0
        output_string = ""
        for i in range(n-2):
            for j in range(i+1, n-1):
                for k in range(j+1, n):
                    count += 1
                    print "%d %d %d" %(i,j, k)
                    """
                    output_string += self.cards[i].__str__() + " " + self.cards[j].__str__() + \
                                     self.cards[k].__str__() + " " + self.cards[l].__str__() + \
                                     self.cards[m].__str__() +  "\n"
                    """
        print count
        print output_string

class card:
    validsuits = ['S', 's', 'H', 'h', 'C', 'c', 'D', 'd']

    def __init__(self, value=None, suit=None):
        """instantiates a single card based on inputs value and suit

           valid input card values are numerical 1-14(where 11 is J, 12 is Q, 13 is K, 14 is A
           and str '1' to '10', 'x', 'j', 'q', 'k', 'a'
           Aces can be represented by 'a' or '1'
           Tens can be represented by 'x' or '10'

           valid suits are 's', 'h,', 'c,', 'd',

           Case does not matter for card values or card suit

           Data is stored internally as card values 2-14 (ace is 14, NOT 1) 
           and for card suits, s/h/c/d (all lowercase)
           """

        if value == None:
            #if card value is not given, then use random card value
            value = random.randrange(2, 15)
        if suit == None:
            #if suit is not given, then use random suit
            suit = random.randrange(4)
            if suit == 0:
                suit = 's'
            elif suit == 1:
                suit = 'h'
            elif suit == 2:
                suit = 'c'
            else:
                suit = 's'

        assert(card.validsuits.__contains__(suit))

        try:
            value = int(value)
            if value == 1:
                value = 14
        except:
            #try these as well
            if value == 'x' or value == 'X':
                value = 10
            elif value == 'j' or value == 'J':
                value = 11
            elif value == 'q' or value == 'Q':
                value = 12
            elif value == 'k' or value == 'K':
                value = 13
            elif value == 'a' or value == 'A':
                value = 14
        assert( 2 <= value <=14)

        self.value = value
        self.suit = suit

    def __str__(self):
        value = self.value
        if value == 10:
            value = 'X'
        elif value == 11:
            value = 'J'
        elif value == 12:
            value = 'Q'
        elif value == 13:
            value = 'K'
        elif value == 14:
            value = 'A'
        suit = self.suit
        return "%s%s" % (value, suit)

    def __cmp__(self, b):
        try:
            return b.value - self.value 
        except:
            return NotImplemented


    def same_suit(self , b):
        return self.suit == b.suit

    @staticmethod
    def has_same_value(list_of_cards):
        """given a list of either 2, 3, 4, 5 cards
           return true if all have same values, else return false"""
        listlen = len(list_of_cards)
        assert( 2 <= listlen <= 5)

        #list_of_cards.sort()
        if listlen == 2:
            #if has 2 cards, check if both  have same values
            return list_of_cards[0].value == list_of_cards[1].value
        elif listlen == 3:
            #if has 3 cards, check if all 3 have same values
            return list_of_cards[0].value == list_of_cards[1].value == list_of_cards[2].value 
        elif listlen == 4:
            #if has 4 cards, check if all 4 have same values
            return list_of_cards[0].value == list_of_cards[1].value ==\
                list_of_cards[2].value == list_of_cards[3].value
        else:
            return False

    @staticmethod
    def card_to_rawnumber(inputcard):
        """all cards can be represented in a compact byte to save on storage space
           value is calculated by taking card's value and adding:
           0x30 if suit is spade (0x30 is 30hex = 3*16decimal)
           0x20h if suit is hearts
           0x10h if suit is clubs
           0x00h if suit is diamonds
           eg Xs (10 spades) is 10+0x30=10*3*16=58 = 0x3A
           eg Ad(acediamond) is 14+0x0 =14 = 0xE
           """
        rawnumber = 0
        if inputcard.suit == 's':
            rawnumber = inputcard.value + 0x30 #magic numbers
        elif inputcard.suit == 'h':
            rawnumber = inputcard.value + 0x20
        elif inputcard.suit == 'c':
            rawnumber = inputcard.value + 0x10
        elif inputcard.suit == 'd':
            rawnumber = inputcard.value
        else:
            raise Exception("inputcard in card_to_rawnumber() has invalid suit")
        return rawnumber

    @staticmethod
    def rawnumber_to_card(card_rawnumber):
        """reverse of card_to_rawnumber()
           returns tuple of [value and suit], eg for input Ad, returns ['13', 's']"""

        #0x30, 0x20, 0x10 are magic numbers
        if  2 + 0x30 <= card_rawnumber <= 14 + 0x30:
            return [card_rawnumber-0x30, 's']
        elif  2 + 0x20 <= card_rawnumber <= 14 + 0x20:
            return [card_rawnumber-0x20, 'h']
        elif  2 + 0x10 <= card_rawnumber <= 14 + 0x10:
            return [card_rawnumber-0x10, 'c']
        elif  2 <= card_rawnumber <= 14:
            return [card_rawnumber, 'd']
        else:
            raise Exception("card_rawnumber is invalid in rawnumber()")

def test():
    """
    c5 =  card(6, "s")
    c1 =  card(7, "s")
    c2 =  card(9, "h")
    c3 =  card(8, "s")
    c4 =  card(10, "s")
    #print "%s %s %s %s %s" % (c1, c2, c3, c4, c5)

    h1 = hand()
    h2 = hand()
    print h1
    print h2
    print h1 > h1
    """

    #cProfile.run('game().permutation_of_5_cards()')
    #cProfile.run('game().permutation_of_7_cards()')
    #cProfile.run("""database.write_5hands_rank_and_highcards(file('z.txt', 'wb'))""")
    database.write_5hands_rank_and_highcards(file('z.txt', 'wb'))
    #cProfile.run("""database.write_7hands_rank_and_highcards(file('z.txt', 'wb'))""")

if __name__ == '__main__':
    test()

